/*
 * This file is part of the Code::Blocks IDE and licensed under the GNU General Public License, version 3
 * http://www.gnu.org/licenses/gpl-3.0.html
 */

#ifndef PARSERTHREAD_H
#define PARSERTHREAD_H

#include <wx/dynarray.h>
#include <wx/event.h>
#include <wx/string.h>
#include <wx/thread.h>

#include <queue>
#include <vector>

#include <cbthreadpool.h>
#include <filemanager.h>
#include <logmanager.h> // F()

#include "cclogger.h"
#include "tokenizer.h"
#include "token.h"
#include "tokentree.h"


struct NameSpace
{
    wxString Name;  // namespace's name
    int StartLine;  // namespace start line (the line contains openbrace)
    int EndLine;    // namespace end line (the line contains closebrace)
};

typedef std::vector<NameSpace> NameSpaceVec;

class ParserBase;

struct ParserThreadOptions
{
    ParserThreadOptions() :

        useBuffer(false),
        fileOfBuffer(),
        parentIdxOfBuffer(-1),
        initLineOfBuffer(1),
        bufferSkipBlocks(false),
        bufferSkipOuterBlocks(false),
        isTemp(false),

        followLocalIncludes(true),
        followGlobalIncludes(true),
        wantPreprocessor(true),
        parseComplexMacros(true),
        platformCheck(true),

        handleFunctions(true),
        handleVars(true),
        handleClasses(true),
        handleEnums(true),
        handleTypedefs(true),

        storeDocumentation(false),

        loader(nullptr)
        {}

    /**
     * useBuffer specifies that we're not parsing a file,  but a temporary
     *  buffer. The resulting tokens will be temporary, too,
     *  and will be deleted before the next file is parsed.
     *
     *  useBuffer指定我们不解析文件,而是解析临时缓冲区.
     *  生成的标记也是临时的,在解析下一个文件之前将被删除.
     */
    bool        useBuffer;

    /**
     * which file the buffer belongs to, this usually happens when we parse a piece of the cbEditor
     *  and the cbEditor is associated by a file in hard disk
     *
     *  缓冲区属于哪个文件,当我们解析cbEditor的一部分并且cbEditor与硬盘中的文件关联时,通常会发生这种情况
     */
    wxString    fileOfBuffer;

    /**
     * when parsing a function body, all the tokens are the children of the function token
     * 解析函数体时,所有标记都是函数标记的子级
     * */
    int         parentIdxOfBuffer;

    /** since we are not parsing start from the first line of the file, this is the first line
     *  number of the buffer in the whole file
     *  由于我们不是从文件的第一行开始解析,所以这是整个文件中缓冲区的第一行编号
     */
    int         initLineOfBuffer;

    /**
     * do we parse inside the {...} body
     * 我们在{…}体中解析吗
     * */
    bool        bufferSkipBlocks;

    /**
     * not used
     * 未使用
     * */
    // classes, namespaces and functions
    // 类、命名空间和函数
    bool        bufferSkipOuterBlocks;

    /**
     * this value is passed to the generated Token's m_IsTemp property
     * 此值被传递到生成的令牌的m_IsTemp属性
     * */
    bool        isTemp;

    /**
     * parse the file in #include "file" directive
     * 解析#include"file"指令中的文件
     * */
    bool        followLocalIncludes;

    /**
     * parse the file in #include <file> directive
     * 解析#include<file>指令中的文件
     * */
    bool        followGlobalIncludes;

    /**
     * handle the #if like preprocessor directives, this value is passed to Tokenizer
     * 处理类似#if的预处理器指令,此值被传递给标记器
     * */
    bool        wantPreprocessor;

    /** not used (未使用) */
    bool        parseComplexMacros;

    /** not used (未使用) */
    bool        platformCheck;

    /**
     * whether to parse the functions
     * 是否解析函数
     * */
    bool        handleFunctions;

    /**
     * whether to parse the variable definition
     * 是否解析变量定义
     * */
    bool        handleVars;

    /**
     * whether to parse "class ...." like statement
     * 是否解析"class ...."类语句
     * */
    bool        handleClasses;

    /**
     * whether to parse "enum ..." like statement
     * 是否解析"enum ..."类语句
     * */
    bool        handleEnums;

    /**
     * whether to parse "typedef ..." like statement
     * 是否解析"typedef ..."类语句
     * */
    bool        handleTypedefs;

    /**
     * should tokenizer detect and store doxygen documentation?
     * 标记器应该检测并存储doxygen文档吗？
     * */
    bool        storeDocumentation;

    // if not NULL, load through filemanager (using threads)
    // 如果不为空,则通过文件管理器(filemanager)加载(使用线程)
    LoaderBase* loader;
};

/**
 * 实现功能: A parser threaded task, which can be assigned to the thread task pool, and run there
  *
  * This class represents a worker threaded task for the Code Completion plug-in, the main task is doing the syntax
  * analysis and add every token to the token tree. The Token tree (sometimes, we call it TokenTree ) is a
  * Patricia tree structure, more details can be seen in token.h and token.cpp. The buffer can  either be loaded
  * from a local file or directly used of a wxString.
  *
 * 实现功能:一个解析器线程任务,可以分配给线程任务池,并在那里运行
  * 此类表示代码完成插件的工作线程任务,主要任务是进行语法分析并将每个令牌添加到令牌树中.
  * 令牌树(有时我们称之为TokenTree)是一种Patricia树结构,更多细节可以在Token.h和token.cpp.
  * 缓冲区可以从本地文件加载,也可以直接使用wxString.
 */
class ParserThread : public cbThreadedTask
{
public:
    /**
     * ParserThread constructor.
      * 参数说明: parent the parent Parser object which contain the token tree.
      * 参数说明: bufferOrFilename it's either the filename to open or a wxString buffer already in memory.
      * 参数说明: isLocal determine whether this is a file locally belong to a cbp or in other global paths.
      * 参数说明: parserThreadOptions parser thread options, see ParserThreadOptions Class for details.
      * 参数说明: tokenTree it is the tree structure holding all the tokens, ParserThread will add every token when it parsed.
      *
     * ParserThread 构造函数.
      * 参数说明: parent 包含令牌树的父解析器对象.
      * 参数说明: bufferOrFilename 它要么是要打开的文件名,要么是内存中已有的wxString缓冲区.
      * 参数说明: isLocal 确定这是本地属于cbp的文件还是其他全局路径中的文件.
      * 参数说明: parserThreadOptions 解析器线程选项,有关详细信息,请参阅ParserThreadOptions类.
      * 参数说明: tokenTree 它是一个树结构,保存所有标记,ParserThread将在解析时添加每个标记.
      */
    ParserThread(ParserBase*          parent,
                 const wxString&      bufferOrFilename,
                 bool                 isLocal,
                 ParserThreadOptions& parserThreadOptions,
                 TokenTree*           tokenTree);

    /**
     * ParserThread destructor.
     * 析构函数
     * */
    virtual ~ParserThread();

    /**
     * Do the main job (syntax analysis) here
     * 在这里做主要的工作(语法分析)
      */
    bool Parse();

    /**
     * Get the context "namespace XXX { ... }" directive. It is used to find the initial search scope
     * before CC prompt a suggestion list.
     * Need a critical section locker before call this function!
     * 参数说明: buffer  wxString to be parsed.
     * 参数说明: result  vector containing all the namespace names.
     *
     * 获取上下文"namespace XXX { ... }"指令.它用于在CC提示建议列表之前查找初始搜索范围.
     * 在调用此函数之前需要一个关键分区锁!
     * 参数说明: buffer  要分析的wxString.
     * 参数说明: result  包含所有命名空间名称的向量.
     */
    bool ParseBufferForNamespaces(const wxString& buffer, NameSpaceVec& result);

    /**
     * 获取上下文"using namespace XXX"指令.它用于在CC提示建议列表之前查找初始搜索范围.
     * 参数说明: buffer  要分析的wxString
     * 参数说明: result wxArrayString包含所有命名空间名称.
     */
    bool ParseBufferForUsingNamespace(const wxString& buffer, wxArrayString& result);
    // used in TRACE for debug only
    // 在跟踪中仅用于调试
    wxString GetFilename() { return m_Buffer; }

protected:
    /**
     * specify which "class like type" we are handling: struct or class or union
     * 指定要处理的"类类型"：struct、class或union
     */
    enum EClassType { ctStructure = 0, ctClass = 1, ctUnion = 3 };

    /**
     * Execute() is a virtual function derived from cbThreadedTask class, we should override it here.
     * In the batch parsing mode, a lot of parser threads were generated and executed concurrently, this often happens when user open a project.
     * Every parserthread task will firstly be added to the thread pool, later called automatically from the thread pool.
     *
     * Execute()是从cbThreadedTask类派生的虚函数,我们应该在这里重写它.
     * 在批解析模式下,大量的解析器线程被并发地生成和执行,这通常发生在用户打开一个项目时.
     * 每个parserthread任务将首先添加到线程池中,然后从线程池中自动调用.
     */
    int Execute()
    {
        CC_LOCKER_TRACK_TT_MTX_LOCK(s_TokenTreeMutex)

        bool success = Parse();

        CC_LOCKER_TRACK_TT_MTX_UNLOCK(s_TokenTreeMutex)

        return success ? 0 : 1;
    }

    /**
     * Continuously eat the tokens until we meet one of the matching characters
     * 参数说明: chars wxString includes all the matching characters
     * 参数说明: supportNesting if true, we need to consider the "{" and "}" nesting levels when skipping,
     * 参数说明: singleCharToken if true, only single char tokens (like semicolon, brace etc.) are considered (speeds up parsing for queries like this) in this case,
     * the function returned on a match by nesting/brace level preserved.
     *
     * 不断地接收令牌,直到我们遇到一个匹配的字符
     * 参数说明: chars wxString包含所有匹配字符
     * 参数说明: supportNesting 如果为真,则跳过时需要考虑"{"和"}"嵌套级别,
     * 参数说明: singleCharToken 如果为true,则只考虑单字符标记(如分号、大括号等)(加快对类似查询的分析速度),在这种情况下,通过嵌套/大括号级别在匹配中返回的函数将被保留.
     */
    wxChar SkipToOneOfChars(const wxString& chars, bool supportNesting = false, bool singleCharToken = true);

    /**
     * actually run the syntax analysis
     * 实际运行语法分析
     */
    void DoParse();

    /**
     * skip blocks {}
     * 跳过{}块
     */
    void SkipBlock();

    /**
     * skip the template argument
     * 跳过模板参数(尖括号)
     */
    void SkipAngleBraces();

    /**
     * handle include <XXXX> or include "XXXX" directive. This will internally add another parserThead object associate with the included file to parserthread pool
     * 处理include<XXXX>或include "XXXX"指令.这将在内部将另一个与包含的文件关联的parserhead对象添加到parserthread池中
     */
    void HandleIncludes();

    /**
     * handle the statement: namespace XXX {
     * 处理语句: namespace XXX {
     */
    void HandleNamespace();

    /**
     * handle class declaration
     * 参数说明: ct specify class like type : struct or enum or class
     *
     * 处理类声明
     * 参数说明: ct 指定类类型：struct或enum或class
     */
    void HandleClass(EClassType ct);

    /**
     * handle function declaration or definition
      * 参数说明: name function name
      * 参数说明: isOperator if true, means it is an operator overload function
      * 参数说明: isPointer if true, means it is a function pointer
      *
     * 处理函数声明或定义
      * 参数说明: name 函数名
      * 参数说明: isOperator 如果为true,则表示它是运算符重载函数
      * 参数说明: isPointer 如果为true,则表示它是一个函数指针
      */
    void HandleFunction(wxString& name, bool isOperator = false, bool isPointer = false);

    /**
     * parse for loop arguments:
      * for(int X; ... ; ...)
      *
     * 解释for循环参数:
      * for(int X; ... ; ...)
      */
    void HandleForLoopArguments();

    /**
     * parse arguments like:
      * if(int X = getNumber())
      *解释类似下面的参数:if(int X = getNumber())
      */
    void HandleConditionalArguments();

    /**
     * handle enum declaration
     * 处理枚举声明
     */
    void HandleEnum();

    /**
     * calculate the value assigned to enumerator
     * 计算分配给枚举器的值
     */
    bool CalcEnumExpression(Token* tokenParent, long& result, wxString& peek);

    /**
     * handle typedef directive
     * 处理typedef指令
     * */
    void HandleTypedef();

    /**
     * eg: class ClassA{...} varA, varB, varC
      * This function will read the "varA, varB, varC"
      * return True, if token was handled, false, if an unexpected token was read.
      *
      * 读取读取变量名
      * 例如：class ClassA{...} varA,varB,varC
      * 此函数将读取"varA,varB,varC"
      * 如果令牌(标识符)被处理,返回True,如果一个异常令牌(标识符)被读到,则返回false.
      */
    bool ReadVarNames();

    /** handle class names, e.g., the code below
     *  @code
     *  typedef class AAA{
     *      int m_a;
     *      int m_b;
     *  } BBB,CCC;
     *  @endcode
     *  @param ancestor class name = "AAA"
     *  this function reads the following "BBB" and "CCC", and regard them as derived classes of "AAA"
     *  @return True, if token was handled, false, if an unexpected token was read.
     *
     *  读取类名称
     *  例如下面代码
     *  typedef class AAA{
     *      int m_a;
     *      int m_b;
     *  } BBB,CCC;
     *
     * 参数 祖先类名称(class name = "AAA")
     * 此函数读取以下“BBB”和“CCC”,并将它们视为“AAA”的派生类
     * 返回值 如果令牌(标识)被处理,则返回True,否则如果读到一个令牌(标识)异常,则返回false
     *
     */
    bool ReadClsNames(wxString& ancestor);

    /**
     * read <> as a whole token
     * 读取整个尖括号内容作为整个令牌(标识符)
     */
    wxString ReadAngleBrackets();

    /**
     * add one token to the token tree
      * 参数说明: kind Token type, see @TokenKind Emun for more details
      * 参数说明: name Token name, this is the key string to be searched in the token tree
      * 参数说明: line line number of the source file where the current Token locates
      * 参数说明: implLineStart if this is a function implementation, it is the start of function body
      * 参数说明: implLineEnd like the one above, it is the end line of the function implementation body
      * 参数说明: args if the token type is a function, this is the function arguments
      * 参数说明: isOperator bool variable to determine an operator override function or not
      * 参数说明: isTmpl bool variable to determine it is a function declaration or implementation
      *
     * 添加一个令牌到令牌树
      * 参数说明: kind 令牌类型,有关详细信息,请参见@TokenKind Emun
      * 参数说明: name 令牌名称,这是要在令牌树中搜索的键字符串
      * 参数说明: line 当前令牌(标识符)所在的源文件的行号
      * 参数说明: implLineStart 如果这是一个函数实现,它就是函数体的开始
      * 参数说明: implLineEnd 和上面的一样,它是函数实现体的最后一行
      * 参数说明: args 如果标记类型是函数,则这是函数参数
      * 参数说明: isOperator 用于确定运算符覆盖函数与否的布尔变量
      * 参数说明: isTmpl 布尔变量来确定它是函数声明或实现
      */
    Token* DoAddToken(TokenKind       kind,
                      const wxString& name,
                      int             line,
                      int             implLineStart = 0,
                      int             implLineEnd = 0,
                      const wxString& args = wxEmptyString,
                      bool            isOperator = false,
                      bool            isImpl = false);

    /**
     * return the actual token's base type.
     * e.g.: if the token type string is: "const wxString &"
     * then, the actual token base type is : "wxString"

     * 返回实际令牌的基本类型.
     * 例如:如果令牌类型字符串为:"const wxString&",则实际的令牌基类型为:"wxString"
     */
    wxString GetTokenBaseType();

private:
    /**
     * initialize the m_Buffer, load from local file or use a buffer in memory
     * 初始化m_Buffer,从本地文件加载或使用内存中的缓冲区
     */
    bool InitTokenizer();

    /**
     * if parent is 0, then global namespace will be used, all tokens under parent scope are searched
      * 参数说明: name the search key string
      * 参数说明: parent parent token pointer, we only search under the parent token scope
      * 参数说明: kindMask filter for the result token, only the specified type of tokens were matched
      *
     * 指向存在的令牌?
     * 如果parent为0,则将使用全局命名空间,搜索父作用域下的所有标记
      * 参数说明: name 搜索关键字字符串
      * 参数说明: parent 父令牌指针,我们只在父令牌作用域下搜索
      * 参数说明: kindMask 筛选结果标记,只匹配指定类型的标记(类型掩码)
      */
    Token* TokenExists(const wxString& name, const Token* parent = 0, short int kindMask = 0xFFFF);

    /**
     * Support function overloading
     * 支持函数重载
     */
    Token* TokenExists(const wxString& name, const wxString& baseArgs, const Token* parent, TokenKind kind);

    /**
     * TODO comment here?
     * 这里的待办事项?
     * 从对列中查找令牌(标识符)
      */
    Token* FindTokenFromQueue(std::queue<wxString>& q,
                              Token*                parent = 0,
                              bool                  createIfNotExist = false,
                              Token*                parentIfCreated = 0);

    /**
     * Converts a full argument list (including variable names) to argument types only and strips spaces.
     * eg: if the argument list is like "(const TheClass* the_class = 0x1234, int my_int = 567)"
     * then, the returned argument list is "(const TheClass*,int)"
     * 参数说明: args Full argument list
     * 参数说明: baseArgs argument types only
     * 返回值:  if failed, will return false, so, it must be a variable
     *
     * 获取参数类型列表
     * 将完整的参数列表(包括变量名)转换为仅参数类型并去掉空格.例如：如果参数列表类似于"(const TheClass* the_class = 0x1234, int my_int = 567)",那么返回的参数列表是"(const TheClass*,int)"
     * 参数说明: args 完整参数列表
     * 参数说明: baseArgs 仅参数类型
     * 返回值:  如果失败,将返回false,因此,它必须是一个变量
      */
    bool GetBaseArgs(const wxString & args, wxString& baseArgs);

    /**
     * Read the <xxxx=yyy, zzz> , and store the value in m_TemplateArgs
     * 获取模板参数
     * 读取<xxxx=yyy,zzz>,并将值存储在m_TemplateArgs中
     */
    void GetTemplateArgs();

    /**
     * this function just associate the formal template argument to actual argument
     *  For example, we have such code:
     *  @code
     *  template <typename T> class AAA { T m_aaa;};
     *  AAA<int> bbb;
     *  @endcode
     *  When handling the "bbb", we need to construct a TemplateMap, we store the map
     *  in the "bbb"'s member variable, which is "T"->"int".
     *
     * 此函数只将形式模板参数与实际参数相关联.例如,我们有这样的代码:
     *  @code
     *  template <typename T> class AAA { T m_aaa;};
     *  AAA<int> bbb;
     *  @endcode
     *  在处理"bbb"时,我们需要构造一个TemplateMap(模板映射),我们将该映射存储在“bbb”的成员变量中,即T->int.
     */
    void ResolveTemplateArgs(Token* newToken);

    /**
     * normally the template argument is all in a wxString, this function just split them to a wxArrayString, each element is an actual argument.
     * 通常模板参数都在一个wxString中,这个函数只是将它们拆分成一个wxArrayString,每个元素都是一个实际的参数.
     */
    wxArrayString GetTemplateArgArray(const wxString& templateArgs, bool remove_gt_lt, bool add_last);

    /**
     * Split formal template argument list
     * 拆分形式模板参数列表
     */
    void SplitTemplateFormalParameters(const wxString& templateArgs, wxArrayString& formals);

    /**
     * Split actual template argument list
     * 拆分实际模板参数列表
     */
    void SplitTemplateActualParameters(const wxString& templateArgs, wxArrayString& actuals);

    /**
     * associate formal argument with actual template argument
     * 将形式参数与实际模板参数相关联
     */
    bool ResolveTemplateMap(const wxString& typeStr, const wxArrayString& actuals,
                            std::map<wxString, wxString>& results);

    /**
     * remove template arguments from an expression example: 'std::list<string>' will be separated into 'std::list' and '<string>'
      * 参数说明: expr Complete expression with template arguments
      * 参数说明: expNoArgs Returned expression without template arguments
      * 参数说明: templateArgs The removed template arguments
      *
     * 从表达式中删除模板参数,示例:"std::list<string>"将被分隔为"std::list"和"<string>"
      * 参数说明: expr 带模板参数的完整表达式
      * 参数说明: expNoArgs 返回的表达式没有模板参数
      * 参数说明: templateArgs 删除的模板参数
    */
    void RemoveTemplateArgs(const wxString& expr, wxString &expNoArgs, wxString &templateArgs);

    /**
     * Only for debug
     * 仅用于调试
     */
    bool IsStillAlive(const wxString& funcInfo);

    /**
     * change an anonymous(unnamed) token's name to a human readable name, the m_Str is expect to store the unnamed token name, for example, for parsing the code
     *  @code
     *  struct
     *  {
     *      int x;
     *      float y;
     *  } abc;
     *  @endcode
     *  when we first find an anonymous token, which is named _UnnamedStruct1_2, after this function
     *  call, the anonymous token name will becomes struct1_abc, and m_Str will changed from
     *  _UnnamedStruct1_2 to struct1_abc.
     *
     * 将匿名(未命名)令牌的名称更改为人类可读的名称,m_Str将存储未命名的令牌名称,例如,用于解析代码
     *  @code
     *  struct
     *  {
     *      int x;
     *      float y;
     *  } abc;
     *  @endcode
     *  当我们第一次找到一个匿名令牌,名为_UnnamedStruct1_2,在这个函数调用之后,匿名令牌名将变成struct1_abc,m_Str将从_UnnamedStruct1_2更改为struct1_abc.
     */
    void  RefineAnonymousTypeToken(short int typeMask, wxString alise);

    /**
     * if we regard the parserThread class as a syntax analyzer, then the Tokenizer class is
      * regard as the lexer, which always feeds a wxString by calling m_Tokenizer.GetToken()
      *
     * 如果我们将parserThread类看作语法分析器,那么Tokenizer类就被视为lexer(词法解释器),它总是通过调用m_Tokenizer.GetToken()来提供wxString
      */
    Tokenizer            m_Tokenizer;

    /**
     * a pointer to its parent Parser object, the Parserthread class has two place to communicate
     * with Parser class. m_Parent->ParseFile() when it see an include directive.
     *
     * Parserthread类是指向其父解析器对象的指针,它有两个地方可以与Parser类通信.m_Parent->ParseFile()当它看到include指令时.
     */
    ParserBase*          m_Parent;

    /**
     * a pointer to the token tree, all the tokens will be added to that tree structure
     * 一个指向令牌树的指针,所有令牌都将添加到该树结构中
     */
    TokenTree*           m_TokenTree;

    /**
     * parent Token, for example, when you are parsing in the class member variables, m_LastParent
      * holds a pointer to the current context, which is a token holding class name
      * 父令牌,例如,在解析类成员变量时,m_LastParent持有一个指向当前上下文的指针,这是一个包含类名的令牌
      */
    Token*               m_LastParent;

    /**
     * this member define the scope type of member variables, which is: public, private protected or undefined
     * 此成员定义成员变量的作用域类型,即:public,private,protected或undefined
     */
    TokenScope           m_LastScope;

    /**
     * the file name of the parsing source
     * 分析源的文件名
     */
    wxString             m_Filename;

    /**
     * file size, actually the length of the wxString
     * 文件大小,实际上是wxString的长度
     */
    unsigned int         m_FileSize;

    /**
     * source file index on the "file map tree"
     * “文件映射树”上的源文件索引
     */
    unsigned int         m_FileIdx;

    /**
     * if true, means we are parsing a file which belongs to a C::B project, otherwise, we are
     *  parsing a file not belong to a C::B project(such as a system header file)
     *
     *  如果为true,则表示我们正在分析一个属于C::B项目的文件,否则,我们将分析一个不属于C::B项目的文件(例如系统头文件)
     */
    bool                 m_IsLocal;

    /**
     * This is a very important member variables! It serves as a type stack,
      * eg: parsing the statement: "unsigned int const varA;"
      * we determine 'varA' is a token variable, until we searching to the last semicolon.
      * every token before 'varA' will be pushed to m_Str, at this time
      * m_Str = "unsigned int const"
      *
     * 这是一个非常重要的成员变量!它充当一个类型堆栈,
     * 例如:解析语句:"unsigned int const varA;"
     * 我们确定"varA"是一个标记变量,直到搜索到最后一个分号.
     * "varA"之前的每个令牌都将被推送到m_Str,此时m_Str="unsigned int const"
      */
    wxString             m_Str;

    /**
     * hold the previous token string
     * 保留上一个令牌字符串
     */
    wxString             m_LastToken;

    /**
     * parser options, see the ParserThreadOptions structure
     * 解析器选项,请参见ParserThreadOptions结构
     */
    ParserThreadOptions  m_Options;

    /**
     * for member funcs implementation or a function declaration below
      * eg: int ClassA::FunctionB();
      * EncounteredNamespaces is 'ClassA'
      *
      * 对于成员函数实现或下面的函数声明,
      * 例如：int ClassA::FunctionB();
      * 遇到的命名空间(EncounteredNamespaces)是"ClassA"
      */
    std::queue<wxString> m_EncounteredNamespaces;

    /**
     * namespaces in function return types for a function declaration below:
     * e.g.: ClassC::returnValue ClassA::FunctionB();
     * m_EncounteredTypeNamespaces is 'ClassC'
     *
     * 以下函数声明的函数返回类型中的命名空间:
     * 例如：ClassC::returnValue ClassA::FunctionB();
     * m_EncounteredTypeNamespaces是'ClassC'
     */
    std::queue<wxString> m_EncounteredTypeNamespaces;

    /**
     * globally included namespaces by "using namespace" statement
     * 通过"using namespace"语句全局包含名称空间
     */
    TokenIdxSet          m_UsedNamespacesIds;

    /**
     * TODO: describe me here
     */
    wxString             m_LastUnnamedTokenName;

    /**
     * this makes a difference in unnamed class/struct/enum handling
     * 这使得未命名的类/结构/枚举处理有所不同
     */
    bool                 m_ParsingTypedef;

    /**
     * a wxString holding the parsing buffer, if it is a file in the hard disk, then this stands
     *  for the file name. Otherwise, this is the in memory buffer content.
     *  保存解析缓冲区的wxString,如果它是硬盘中的文件,那么它代表文件名.否则,这就是内存中的缓冲区内容.
     */
    wxString             m_Buffer;

    /**
     * a pointer indicator or a references
     * 指针指示器或引用
     */
    wxString             m_PointerOrRef;

    /**
     * holds current template argument(s) when a template occurs
     * 在模板发生时保存当前模板参数
     */
    wxString             m_TemplateArgument;

    size_t               m_StructUnionUnnamedCount;

    size_t               m_EnumUnnamedCount;
};

#endif // PARSERTHREAD_H
